home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 June / PersonalComputerWorld-June2009-CoverdiscCD.iso / Software / Freeware / Firebug 1.3.3 / firebug-1.3.3-fx.xpi / content / firebug / commandLine.js < prev    next >
Encoding:
JavaScript  |  2009-02-19  |  25.8 KB  |  865 lines

  1. /* See license.txt for terms of usage */
  2.  
  3. FBL.ns(function() { with (FBL) {
  4.  
  5. // ************************************************************************************************
  6. // Constants
  7.  
  8. const commandHistoryMax = 1000;
  9. const commandPrefix = ">>>";
  10.  
  11. const reOpenBracket = /[\[\(\{]/;
  12. const reCloseBracket = /[\]\)\}]/;
  13. const reCmdSource = /^with\(_FirebugCommandLine\){(.*)};$/;
  14.  
  15. // ************************************************************************************************
  16. // GLobals
  17.  
  18. var commandHistory = [""];
  19. var commandPointer = 0;
  20. var commandInsertPointer = -1;
  21.  
  22. // ************************************************************************************************
  23.  
  24. Firebug.CommandLine = extend(Firebug.Module,
  25. {
  26.     
  27.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  28.  
  29.     // targetWindow was needed by evaluateInSandbox, let's leave it for a while in case we rethink this yet again
  30.  
  31.     evaluate: function(expr, context, thisValue, targetWindow, successConsoleFunction, exceptionFunction) // returns user-level wrapped object I guess.
  32.     {
  33.         if (!context)
  34.             return;
  35.  
  36.         var debuggerState = Firebug.Debugger.beginInternalOperation();
  37.         try
  38.         {
  39.             var result = null;
  40.  
  41.             if (context.stopped)
  42.             {
  43.                 result = this.evaluateInDebugFrame(expr, context, thisValue, targetWindow,  successConsoleFunction, exceptionFunction);
  44.             }
  45.             else
  46.             {
  47.                 result = this.evaluateByEventPassing(expr, context, thisValue, targetWindow,  successConsoleFunction, exceptionFunction);
  48.             }
  49.         }
  50.         catch (exc)  // XXX jjb, I don't expect this to be taken, the try here is for the finally
  51.         {
  52.         }
  53.         finally
  54.         {
  55.             Firebug.Debugger.endInternalOperation(debuggerState);
  56.         }
  57.  
  58.         return result;
  59.     },
  60.  
  61.  
  62.     evaluateByEventPassing: function(expr, context, thisValue, targetWindow, successConsoleFunction, exceptionFunction)
  63.     {
  64.         var win = targetWindow ? targetWindow : ( context.baseWindow ? context.baseWindow : context.window );
  65.         if (!win)
  66.         {
  67.             return;
  68.         }
  69.         
  70.         // Make sure the command line script is attached.
  71.         var element = Firebug.Console.getFirebugConsoleElement(context, win);
  72.         if (element)
  73.         {
  74.             var attached = element.getAttribute("firebugCommandLineAttached");
  75.             if (!attached)
  76.             {
  77.                 Firebug.Console.logFormatted(["Firebug cannot find firebugCommandLineAttached attribute on firebug console element, its too early for command line", element, win], context, "error", true);
  78.             }
  79.         }
  80.         else
  81.         {
  82.             return;  // we're in trouble here
  83.         }
  84.  
  85.         var event = document.createEvent("Events");
  86.         event.initEvent("firebugCommandLine", true, false);
  87.         
  88.         
  89.         element.setAttribute("methodName", "evaluate");
  90.  
  91.         expr = expr.toString();
  92.         expr = "with(_FirebugCommandLine){" + expr + "\n};";
  93.         element.setAttribute("expr", expr);
  94.  
  95.         var consoleHandler;
  96.         for (var i=0; i<context.activeConsoleHandlers.length; i++)
  97.         {
  98.             if (context.activeConsoleHandlers[i].window == win)
  99.             {
  100.                 consoleHandler = context.activeConsoleHandlers[i];
  101.                 break;
  102.             }
  103.         }
  104.  
  105.         if (successConsoleFunction)
  106.         {
  107.             consoleHandler.evaluated = function useConsoleFunction(result)
  108.             {
  109.                 successConsoleFunction(result, context);  // result will be pass thru this function
  110.             }
  111.         }
  112.         
  113.         if (exceptionFunction)
  114.         {
  115.             consoleHandler.evaluateError = function useExceptionFunction(result)
  116.             {
  117.                 exceptionFunction(result, context);
  118.             }
  119.         }
  120.         else
  121.         {
  122.             consoleHandler.evaluateError = function useErrorFunction(result)
  123.             {
  124.                 if (result)
  125.                 {
  126.                     var m = reCmdSource.exec(result.source);
  127.                     if (m && m.length > 0)
  128.                         result.source = m[1];
  129.                 }
  130.  
  131.                 Firebug.Console.logFormatted([result], context, "error", true);
  132.             }
  133.         }
  134.  
  135.         element.dispatchEvent(event);
  136.     },
  137.  
  138.     evaluateInDebugFrame: function(expr, context, thisValue, targetWindow,  successConsoleFunction, exceptionFunction)
  139.     {
  140.         var result = null;
  141.         
  142.         // targetWindow may be frame in HTML
  143.         var win = targetWindow ? targetWindow : ( context.baseWindow ? context.baseWindow : context.window );
  144.         
  145.         if (!context.commandLineAPI)
  146.             context.commandLineAPI = new FirebugCommandLineAPI(context, (win.wrappedJSObject?win.wrappedJSObject:win));  // TODO should be baseWindow
  147.  
  148.         var scope = {
  149.             api       : context.commandLineAPI,
  150.             vars      : getInspectorVars(context),
  151.             thisValue : thisValue
  152.         };
  153.  
  154.         try
  155.         {
  156.             result = Firebug.Debugger.evaluate(expr, context, scope);
  157.             successConsoleFunction(result, context);  // result will be pass thru this function
  158.         }
  159.         catch (e)
  160.         {
  161.             exceptionFunction(e, context);
  162.         }
  163.         return result;
  164.     },
  165.  
  166.     // TODO: strip down to minimum, have one global sandbox that is reused.
  167.     evaluateInSandbox: function(expr, context, thisValue, targetWindow, skipNotDefinedMessages)  // returns user-level wrapped object I guess.
  168.     {
  169.         // targetWindow may be frame in HTML
  170.         var win = targetWindow ? targetWindow : ( context.baseWindow ? context.baseWindow : context.window );
  171.  
  172.         if (!context.sandboxes)
  173.             context.sandboxes = [];
  174.  
  175.         var sandbox = this.getSandboxByWindow(context, win);
  176.         if (!sandbox)
  177.         {
  178.             sandbox = new Components.utils.Sandbox(win); // Use DOM Window
  179.             sandbox.__proto__ = (win.wrappedJSObject?win.wrappedJSObject:win); //  XPCNativeWrapper vs  XPCSafeJSObjectWrapper
  180.             context.sandboxes.push(sandbox); // XXXdolske does this get cleared?  LEAK?
  181.         }
  182.  
  183.         var scriptToEval = expr;
  184.  
  185.         // If we want to use a specific |this|, wrap the expression with Function.apply()
  186.         // and inject the new |this| into the sandbox so it's easily accessible.
  187.         if (thisValue) {
  188.             // XXXdolske is this safe if we're recycling the sandbox?
  189.             sandbox.__thisValue__ = thisValue;
  190.             scriptToEval = "(function() { return " + scriptToEval + " \n}).apply(__thisValue__);";
  191.         }
  192.  
  193.         // Page scripts expect |window| to be the global object, not the
  194.         // sandbox object itself. Stick window into the scope chain so
  195.         // assignments like |foo = bar| are effectively |window.foo =
  196.         // bar|, else the page won't see the new value.
  197.         scriptToEval = "with (window?window:null) { " + scriptToEval + " \n};";
  198.  
  199.         try {
  200.             result = Components.utils.evalInSandbox(scriptToEval, sandbox);
  201.         } catch (e) {
  202.             result = new FBL.ErrorMessage("commandLine.evaluate FAILED: " + e, this.getDataURLForContent(scriptToEval, "FirebugCommandLineEvaluate"), e.lineNumber, 0, "js", context, null);
  203.         }
  204.         return result;
  205.     },
  206.  
  207.     getSandboxByWindow: function(context, win)
  208.     {
  209.         for (var i = 0; i < context.sandboxes.length; i++) {
  210.             // XXXdolske is accessing .window safe after untrusted script has run?
  211.             if (context.sandboxes[i].window === win.wrappedJSObject)
  212.                 return context.sandboxes[i];
  213.         }
  214.         return null;
  215.     },
  216.  
  217.     getDataURLForContent: function(content, url)
  218.     {
  219.         // data:text/javascript;fileName=x%2Cy.js;baseLineNumber=10,<the-url-encoded-data>
  220.         var uri = "data:text/html;";
  221.         uri += "fileName="+encodeURIComponent(url)+ ","
  222.         uri += encodeURIComponent(content);
  223.         return uri;
  224.     },
  225.  
  226.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  227.  
  228.     enter: function(context, command)
  229.     {
  230.         var commandLine = getCommandLine(context);
  231.         var expr = command ? command : commandLine.value;
  232.         if (expr == "")
  233.             return;
  234.  
  235.         if (!Firebug.largeCommandLine)
  236.         {
  237.             this.clear(context);
  238.             this.appendToHistory(expr);
  239.  
  240.             Firebug.Console.log(commandPrefix + " " + expr, context, "command", FirebugReps.Text);
  241.         }
  242.         else
  243.         {
  244.             var shortExpr = cropString(stripNewLines(expr), 100);
  245.             Firebug.Console.log(commandPrefix + " " + shortExpr, context, "command", FirebugReps.Text);
  246.         }
  247.  
  248.         this.evaluate(expr, context, null, null, FBL.bind(Firebug.Console.log, Firebug.Console));  
  249.     },
  250.  
  251.     enterMenu: function(context)
  252.     {
  253.         var commandLine = getCommandLine(context);
  254.         var expr = commandLine.value;
  255.         if (expr == "")
  256.             return;
  257.  
  258.         this.appendToHistory(expr, true);
  259.  
  260.         this.evaluate(expr, context, null, null, function(result, context)
  261.         {
  262.             if (typeof(result) != "undefined")
  263.             {
  264.                 context.chrome.contextMenuObject = result;
  265.  
  266.                 var popup = context.chrome.$("fbContextMenu");
  267.                 popup.showPopup(commandLine, -1, -1, "popup", "bottomleft", "topleft");
  268.             }
  269.         });
  270.     },
  271.  
  272.     enterInspect: function(context)
  273.     {
  274.         var commandLine = getCommandLine(context);
  275.         var expr = commandLine.value;
  276.         if (expr == "")
  277.             return;
  278.  
  279.         this.clear(context);
  280.         this.appendToHistory(expr);
  281.  
  282.         this.evaluate(expr, context, null, null, function(result, context)
  283.         {
  284.             if (typeof(result) != undefined)
  285.                 context.chrome.select(result);
  286.         });
  287.     },
  288.  
  289.     reenter: function(context)
  290.     {
  291.         var command = commandHistory[commandInsertPointer];
  292.         if (command)
  293.             this.enter(context, command);
  294.     },
  295.  
  296.     copyBookmarklet: function(context)
  297.     {
  298.         var commandLine = getCommandLine(context);
  299.         var expr = "javascript: " + stripNewLines(commandLine.value);
  300.         copyToClipboard(expr);
  301.     },
  302.  
  303.     focus: function(context)
  304.     {
  305.         if (context.detached)
  306.             context.chrome.focus();
  307.         else
  308.             Firebug.toggleBar(true);
  309.  
  310.         context.chrome.selectPanel("console");
  311.  
  312.         var commandLine = getCommandLine(context);
  313.         setTimeout(function() { commandLine.select(); });
  314.     },
  315.  
  316.     clear: function(context)
  317.     {
  318.         var commandLine = getCommandLine(context);
  319.         commandLine.value = context.commandLineText = "";
  320.         this.autoCompleter.reset();
  321.     },
  322.  
  323.     cancel: function(context)
  324.     {
  325.         var commandLine = getCommandLine(context);
  326.         if (!this.autoCompleter.revert(commandLine))
  327.             this.clear(context);
  328.     },
  329.  
  330.     update: function(context)
  331.     {
  332.         var commandLine = getCommandLine(context);
  333.         context.commandLineText = commandLine.value;
  334.         this.autoCompleter.reset();
  335.     },
  336.  
  337.     complete: function(context, reverse)
  338.     {
  339.         var commandLine = getCommandLine(context);
  340.         this.autoCompleter.complete(context, commandLine, true, reverse);
  341.         context.commandLineText = commandLine.value;
  342.     },
  343.  
  344.     setMultiLine: function(multiLine)
  345.     {
  346.         if (FirebugContext && FirebugContext.panelName != "console")
  347.             return;
  348.  
  349.         var chrome = FirebugContext ? FirebugContext.chrome : FirebugChrome;
  350.         chrome.$("fbCommandBox").collapsed = multiLine;
  351.         chrome.$("fbPanelSplitter").collapsed = !multiLine;
  352.         chrome.$("fbSidePanelDeck").collapsed = !multiLine;
  353.         if (multiLine)
  354.             chrome.$("fbSidePanelDeck").selectedPanel = chrome.$("fbLargeCommandBox");
  355.  
  356.         var commandLineSmall = chrome.$("fbCommandLine");
  357.         var commandLineLarge = chrome.$("fbLargeCommandLine");
  358.  
  359.         if (multiLine)
  360.             commandLineLarge.value = cleanIndentation(commandLineSmall.value);
  361.         else
  362.             commandLineSmall.value = stripNewLines(commandLineLarge.value);
  363.     },
  364.  
  365.     toggleMultiLine: function(forceLarge)
  366.     {
  367.         var large = forceLarge || !Firebug.largeCommandLine;
  368.         if (large != Firebug.largeCommandLine)
  369.             Firebug.setPref(Firebug.prefDomain, "largeCommandLine", large);
  370.     },
  371.  
  372.     checkOverflow: function(context)
  373.     {
  374.         if (!context)
  375.             return;
  376.  
  377.         var commandLine = getCommandLine(context);
  378.         if (commandLine.value.indexOf("\n") >= 0)
  379.         {
  380.             setTimeout(bindFixed(function()
  381.             {
  382.                 Firebug.setPref(Firebug.prefDomain, "largeCommandLine", true);
  383.             }, this));
  384.         }
  385.     },
  386.  
  387.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  388.  
  389.     appendToHistory: function(command, unique)
  390.     {
  391.         if (unique && commandHistory[commandInsertPointer] == command)
  392.             return;
  393.  
  394.         ++commandInsertPointer;
  395.         if (commandInsertPointer >= commandHistoryMax)
  396.             commandInsertPointer = 0;
  397.  
  398.         commandPointer = commandInsertPointer+1;
  399.         commandHistory[commandInsertPointer] = command;
  400.     },
  401.  
  402.     cycleCommandHistory: function(context, dir)
  403.     {
  404.         var commandLine = getCommandLine(context);
  405.  
  406.         commandHistory[commandPointer] = commandLine.value;
  407.  
  408.         if (dir < 0)
  409.         {
  410.             --commandPointer;
  411.             if (commandPointer < 0)
  412.                 commandPointer = 0;
  413.         }
  414.         else
  415.         {
  416.             ++commandPointer;
  417.             if (commandPointer > commandInsertPointer+1)
  418.                 commandPointer = commandInsertPointer+1;
  419.         }
  420.  
  421.         var command = commandHistory[commandPointer];
  422.  
  423.         this.autoCompleter.reset();
  424.  
  425.         commandLine.value = context.commandLineText = command;
  426.         commandLine.inputField.setSelectionRange(command.length, command.length);
  427.     },
  428.  
  429.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  430.     // extends Module
  431.  
  432.     initialize: function()
  433.     {
  434.         this.autoCompleter = new Firebug.AutoCompleter(getExpressionOffset, getDot,
  435.             autoCompleteEval, false, true);
  436.  
  437.         if (Firebug.largeCommandLine)
  438.             this.setMultiLine(true);
  439.     },
  440.  
  441.     showContext: function(browser, context)
  442.     {
  443.         if (context)  // null for eg about:crashes
  444.         {
  445.             var chrome = context ? context.chrome : FirebugChrome;
  446.             if (chrome)
  447.             {
  448.                 var command = chrome.$("cmd_focusCommandLine");
  449.                 command.setAttribute("disabled", !context);
  450.             }
  451.         }
  452.     },
  453.  
  454.     showPanel: function(browser, panel)
  455.     {
  456.         var chrome = browser.chrome;
  457.  
  458.         var isConsole = panel && panel.name == "console";
  459.         if (Firebug.largeCommandLine)
  460.         {
  461.             if (isConsole)
  462.             {
  463.                 chrome.$("fbPanelSplitter").collapsed = false;
  464.                 chrome.$("fbSidePanelDeck").collapsed = false;
  465.                 chrome.$("fbSidePanelDeck").selectedPanel = chrome.$("fbLargeCommandBox");
  466.                 collapse(chrome.$("fbCommandBox"), true);
  467.             }
  468.         }
  469.         else
  470.             collapse(chrome.$("fbCommandBox"), !isConsole);
  471.  
  472.         var value = panel ? panel.context.commandLineText : null;
  473.         var commandLine = getCommandLine(browser);
  474.         commandLine.value = value ? value : "";
  475.     },
  476.  
  477.     updateOption: function(name, value)
  478.     {
  479.         if (name == "largeCommandLine")
  480.             this.setMultiLine(value);
  481.     },
  482.     
  483.     // called by users of command line, currently:
  484.     // 1) Console on focus command line, 2) Watch onfocus, and 3) debugger loadedContext if watches exist
  485.     isNeededGetReady: function(context, win) 
  486.     {
  487.         if (win)
  488.             Firebug.CommandLine.injector.attachCommandLine(context, win);
  489.         else
  490.         {
  491.             Firebug.CommandLine.injector.attachCommandLine(context, context.window);
  492.             for (var i = 0; i < context.windows.length; i++)
  493.                 Firebug.CommandLine.injector.attachCommandLine(context, context.windows[i]);
  494.         }
  495.         
  496.         // the attach is asynchronous, we can report when it is complete:
  497.         if (context.window.wrappedJSObject._FirebugCommandLine)
  498.             return true;
  499.         else
  500.             return false;
  501.     },
  502. });
  503.  
  504. // ************************************************************************************************
  505. // Shared Helpers
  506.  
  507. Firebug.CommandLine.CommandHandler = extend(Object,
  508. {
  509.     handle: function(event, api, win)
  510.     {
  511.         var element = event.target;
  512.         var methodName = element.getAttribute("methodName");
  513.         var hosed_userObjects = (win.wrappedJSObject?win.wrappedJSObject:win)._firebug.userObjects;
  514.  
  515.         var userObjects = hosed_userObjects ? cloneArray(hosed_userObjects) : [];
  516.         var subHandler = api[methodName];
  517.         if (!subHandler)
  518.             return false;
  519.  
  520.         element.removeAttribute("retValueType");
  521.         var result = subHandler.apply(api, userObjects);
  522.         if (typeof result != "undefined")
  523.         {
  524.             if (result instanceof Array)
  525.             {
  526.                 element.setAttribute("retValueType", "array");
  527.                 for (var item in result)
  528.                     hosed_userObjects.push(result[item]);
  529.             }
  530.             else
  531.             {
  532.                 hosed_userObjects.push(result);
  533.             }
  534.         }
  535.  
  536.         return true;
  537.     }
  538. });
  539.  
  540. // ************************************************************************************************
  541. // Local Helpers
  542.  
  543. function getExpressionOffset(command, offset)
  544. {
  545.     // XXXjoe This is kind of a poor-man's JavaScript parser - trying
  546.     // to find the start of the expression that the cursor is inside.
  547.     // Not 100% fool proof, but hey...
  548.  
  549.     var bracketCount = 0;
  550.  
  551.     var start = command.length-1;
  552.     for (; start >= 0; --start)
  553.     {
  554.         var c = command[start];
  555.         if ((c == "," || c == ";" || c == " ") && !bracketCount)
  556.             break;
  557.         if (reOpenBracket.test(c))
  558.         {
  559.             if (bracketCount)
  560.                 --bracketCount;
  561.             else
  562.                 break;
  563.         }
  564.         else if (reCloseBracket.test(c))
  565.             ++bracketCount;
  566.     }
  567.  
  568.     return start + 1;
  569. }
  570.  
  571. function getDot(expr, offset)
  572. {
  573.     var lastDot = expr.lastIndexOf(".");
  574.     if (lastDot == -1)
  575.         return null;
  576.     else
  577.         return {start: lastDot+1, end: expr.length-1};
  578. }
  579.  
  580. function autoCompleteEval(preExpr, expr, postExpr, context)
  581. {
  582.     try
  583.     {
  584.         if (preExpr)
  585.         {
  586.             // Remove the trailing dot (if there is one)
  587.             var lastDot = preExpr.lastIndexOf(".");
  588.             if (lastDot != -1)
  589.                 preExpr = preExpr.substr(0, lastDot);
  590.  
  591.             var self = this;
  592.             Firebug.CommandLine.evaluate(preExpr, context, context.thisValue, null,
  593.                 function found(result, context)
  594.                 {
  595.                     self.complete = keys(result).sort();
  596.                 },
  597.                 function failed(result, context)
  598.                 {    
  599.                     self.complete = [];
  600.                 }
  601.             );
  602.             return self.complete;
  603.         }
  604.         else
  605.         {
  606.             if (context.stopped)
  607.                 return Firebug.Debugger.getCurrentFrameKeys(context);
  608.             else
  609.                 return keys(context.window.wrappedJSObject).sort();  // return is safe
  610.         }
  611.     }
  612.     catch (exc)
  613.     {
  614.         return [];
  615.     }
  616. }
  617.  
  618. function injectScript(script, win)
  619. {
  620.     win.location = "javascript: " + script;
  621. }
  622.  
  623. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  624.  
  625. function getInspectorVars(context)
  626. {
  627.     var htmlPanel = context.getPanel("html", true);
  628.     var vars = {};
  629.     for (var i=0; i<2; i++)
  630.         vars["$"+i] = htmlPanel ? htmlPanel.inspectorHistory[i] : null;
  631.  
  632.     return vars;
  633. }
  634.  
  635. function getCommandLine(context)
  636. {
  637.     return Firebug.largeCommandLine
  638.         ? context.chrome.$("fbLargeCommandLine")
  639.         : context.chrome.$("fbCommandLine");
  640. }
  641.  
  642. const reIndent = /^(\s+)/;
  643.  
  644. function getIndent(line)
  645. {
  646.     var m = reIndent.exec(line);
  647.     return m ? m[0].length : 0;
  648. }
  649.  
  650. function cleanIndentation(text)
  651. {
  652.     var lines = splitLines(text);
  653.  
  654.     var minIndent = -1;
  655.     for (var i = 0; i < lines.length; ++i)
  656.     {
  657.         var line = lines[i];
  658.         var indent = getIndent(line);
  659.         if (minIndent == -1 && line && !isWhitespace(line))
  660.             minIndent = indent;
  661.         if (indent >= minIndent)
  662.             lines[i] = line.substr(minIndent);
  663.     }
  664.     return lines.join("\n");
  665. }
  666.  
  667. // ************************************************************************************************
  668. // Command line APIs definition
  669.  
  670. function FirebugCommandLineAPI(context, baseWindow)
  671. {
  672.     this.$ = function(id)
  673.     {
  674.         var doc = baseWindow.document;
  675.         return baseWindow.document.getElementById(id);
  676.     };
  677.  
  678.     this.$$ = function(selector)
  679.     {
  680.         return FBL.getElementsBySelector(baseWindow.document, selector);
  681.     };
  682.  
  683.     this.$x = function(xpath)
  684.     {
  685.         return FBL.getElementsByXPath(baseWindow.document, xpath);
  686.     };
  687.  
  688.     this.$n = function(index)
  689.     {
  690.         var htmlPanel = context.getPanel("html", true);
  691.         if (!htmlPanel)
  692.             return null;
  693.  
  694.         if (index < 0 || index >= htmlPanel.inspectorHistory.length)
  695.             return null;
  696.  
  697.         var node = htmlPanel.inspectorHistory[index];
  698.         if (!node)
  699.             return node;
  700.  
  701.         return node.wrappedJSObject;
  702.     };
  703.  
  704.     this.cd = function(object)
  705.     {
  706.         if (!(object instanceof Window))
  707.             throw "Object must be a window.";
  708.  
  709.         // The window object parameter uses XPCSafeJSObjectWrapper, but we need XPCNativeWrapper 
  710.         // (and its wrappedJSObject member). So, look within all registered consoleHandlers for 
  711.         // the same window (from tabWatcher) that uses uses XPCNativeWrapper (operator "==" works).
  712.         for (var i=0; i<context.activeConsoleHandlers.length; i++) {
  713.             if (context.activeConsoleHandlers[i].window == object) {
  714.                 baseWindow = context.baseWindow = context.activeConsoleHandlers[i].window;
  715.                 break;
  716.             }
  717.         }
  718.         
  719.         Firebug.Console.log(["Current window:", context.baseWindow], context, "info");
  720.     };
  721.  
  722.     this.clear = function()
  723.     {
  724.         Firebug.Console.clear(context);
  725.     };
  726.  
  727.     this.inspect = function(obj, panelName)
  728.     {
  729.         context.chrome.select(obj, panelName);
  730.     };
  731.  
  732.     this.keys = function(o)
  733.     {
  734.         return FBL.keys(o);
  735.     };
  736.  
  737.     this.values = function(o)
  738.     {
  739.         return FBL.values(o);
  740.     };
  741.  
  742.     this.debug = function(fn)
  743.     {
  744.         Firebug.Debugger.trace(fn, null, "debug");
  745.     };
  746.  
  747.     this.undebug = function(fn)
  748.     {
  749.         Firebug.Debugger.untrace(fn, null, "debug");
  750.     };
  751.  
  752.     this.monitor = function(fn)
  753.     {
  754.         Firebug.Debugger.trace(fn, null, "monitor");
  755.     };
  756.  
  757.     this.unmonitor = function(fn)
  758.     {
  759.         Firebug.Debugger.untrace(fn, null, "monitor");
  760.     };
  761.  
  762.     this.monitorEvents = function(object, types)
  763.     {
  764.         monitorEvents(object, types, context);
  765.     };
  766.  
  767.     this.unmonitorEvents = function(object, types)
  768.     {
  769.         unmonitorEvents(object, types, context);
  770.     };
  771.  
  772.     this.profile = function(title)
  773.     {
  774.         Firebug.Profiler.startProfiling(context, title);
  775.     };
  776.  
  777.     this.profileEnd = function()
  778.     {
  779.         Firebug.Profiler.stopProfiling(context);
  780.     };
  781.  
  782.     this.copy = function(x)
  783.     {
  784.         FBL.copyToClipboard(x);
  785.     };
  786. }
  787.  
  788. // ************************************************************************************************
  789.  
  790. Firebug.CommandLine.injector = {
  791.  
  792.     attachCommandLine: function(context, win)
  793.     {
  794.         if (!win)
  795.             return;
  796.  
  797.         // If the command line is already attached then end.
  798.         var doc = win.document;
  799.         if ($("_firebugCommandLineInjector", doc))
  800.             return;
  801.  
  802.         if (context.stopped)
  803.             Firebug.CommandLine.injector.evalCommandLineScript(context);
  804.         else
  805.             Firebug.CommandLine.injector.injectCommandLineScript(doc);
  806.  
  807.         Firebug.CommandLine.injector.addCommandLineListener(context, win, doc);
  808.     },
  809.  
  810.     evalCommandLineScript: function(context)
  811.     {
  812.         var scriptSource = getResource("chrome://firebug/content/commandLineInjected.js");
  813.         Firebug.Debugger.evaluate(scriptSource, context);
  814.     },
  815.  
  816.     injectCommandLineScript: function(doc)
  817.     {
  818.         // Inject command line script into the page.
  819.         var scriptSource = getResource("chrome://firebug/content/commandLineInjected.js");
  820.         addScript(doc, "_firebugCommandLineInjector", scriptSource);
  821.     },
  822.  
  823.     addCommandLineListener: function(context, win, doc)
  824.     {
  825.         // Register listener for command-line execution events.
  826.         var handler = new CommandLineHandler(context, win);
  827.         var element = Firebug.Console.getFirebugConsoleElement(context, win);
  828.         element.addEventListener("firebugExecuteCommand", bind(handler.handleEvent, handler) , true);
  829.     }
  830. };
  831.  
  832. function CommandLineHandler(context, win)
  833. {
  834.     this.handleEvent = function(event)  // win is the window the handler is bound into 
  835.     {
  836.         var baseWindow = context.baseWindow? context.baseWindow : context.window;
  837.         this.api = new FirebugCommandLineAPI(context,  baseWindow.wrappedJSObject);
  838.  
  839.         var vars = getInspectorVars(context);
  840.         for (var prop in vars)
  841.         {
  842.             function createHandler(p) {
  843.                 return function() {
  844.                     return vars[p] ? vars[p].wrappedJSObject : null;
  845.                 }
  846.             }
  847.             this.api[prop] = createHandler(prop);  // XXXjjb should these be removed?
  848.         }
  849.  
  850.         if (!Firebug.CommandLine.CommandHandler.handle(event, this.api, win))
  851.         {
  852.             var methodName = event.target.getAttribute("methodName");
  853.             Firebug.Console.log($STRF("commandline.MethodNotSupported", [methodName]));
  854.         }
  855.     };
  856. }
  857.  
  858. // ************************************************************************************************
  859.  
  860. Firebug.registerModule(Firebug.CommandLine);
  861.  
  862. // ************************************************************************************************
  863.  
  864. }});
  865.